home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-ARM / CHECKSUM.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  4KB  |  163 lines

  1. /*
  2.  * linux/include/asm-arm/checksum.h
  3.  *
  4.  * IP checksum routines
  5.  *
  6.  * Copyright (C) Original authors of ../asm-i386/checksum.h
  7.  * Copyright (C) 1996,1997,1998 Russell King
  8.  */
  9. #ifndef __ASM_ARM_CHECKSUM_H
  10. #define __ASM_ARM_CHECKSUM_H
  11.  
  12. #ifndef __ASM_ARM_SEGMENT_H
  13. #include <asm/segment.h>
  14. #endif
  15.  
  16. /*
  17.  * computes the checksum of a memory block at buff, length len,
  18.  * and adds in "sum" (32-bit)
  19.  *
  20.  * returns a 32-bit number suitable for feeding into itself
  21.  * or csum_tcpudp_magic
  22.  *
  23.  * this function must be called with even lengths, except
  24.  * for the last fragment, which may be odd
  25.  *
  26.  * it's best to have buff aligned on a 32-bit boundary
  27.  */
  28. unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
  29.  
  30. /*
  31.  * the same as csum_partial, but copies from src while it
  32.  * checksums, and handles user-space pointer exceptions correctly, when needed.
  33.  *
  34.  * here even more important to align src and dst on a 32-bit (or even
  35.  * better 64-bit) boundary
  36.  */
  37.  
  38. unsigned int
  39. csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
  40.  
  41. unsigned int
  42. csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
  43.  
  44. #if 0
  45. /*
  46.  * This combination is currently not used, but possible:
  47.  */
  48. unsigned int
  49. csum_partial_copy_to_user(const char *src, char *dst, int len, int sum, int *err_ptr);
  50. #endif
  51.  
  52. /*
  53.  * These are the old (and unsafe) way of doing checksums, a warning message will be
  54.  * printed if they are used and an exception occurs.
  55.  *
  56.  * these functions should go away after some time.
  57.  */
  58. #define csum_partial_copy_fromuser csum_partial_copy
  59. unsigned int
  60. csum_partial_copy(const char *src, char *dst, int len, int sum);
  61.  
  62. /*
  63.  *    This is a version of ip_compute_csum() optimized for IP headers,
  64.  *    which always checksum on 4 octet boundaries.
  65.  *
  66.  *    Converted and optimised for ARM by R. M. King.
  67.  *
  68.  *    Note: the order that the LDM registers are loaded with respect to
  69.  *    the adc's doesn't matter.
  70.  */
  71. static inline unsigned short
  72. ip_fast_csum(unsigned char * iph, unsigned int ihl)
  73. {
  74.     unsigned int sum, tmp1;
  75.  
  76.     __asm__ __volatile__("
  77.     sub    %2, %2, #5
  78.     ldr    %0, [%1], #4
  79.     ldr    %3, [%1], #4
  80.     adds    %0, %0, %3
  81.     ldr    %3, [%1], #4
  82.     adcs    %0, %0, %3
  83.     ldr    %3, [%1], #4
  84.     adcs    %0, %0, %3
  85. 1:    ldr    %3, [%1], #4
  86.     adcs    %0, %0, %3
  87.     tst    %2, #15
  88.     subne    %2, %2, #1
  89.     bne    1b
  90.     adc    %0, %0, #0
  91.     adds    %0, %0, %0, lsl #16
  92.     addcs    %0, %0, #0x10000
  93.     mvn    %0, %0
  94.     mov    %0, %0, lsr #16
  95.     "
  96.     : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (tmp1)
  97.     : "1" (iph), "2" (ihl));
  98.     return(sum);
  99. }
  100.  
  101. /*
  102.  *     Fold a partial checksum without adding pseudo headers
  103.  */
  104. static inline unsigned int
  105. csum_fold(unsigned int sum)
  106. {
  107.     __asm__("
  108.     adds    %0, %0, %0, lsl #16
  109.     addcs    %0, %0, #0x10000"
  110.     : "=r" (sum)
  111.     : "0" (sum));
  112.     return (~sum) >> 16;
  113. }
  114.  
  115. static inline unsigned long
  116. csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
  117.            unsigned short proto, unsigned int sum)
  118. {
  119.     __asm__("
  120.     adds    %0, %0, %1
  121.     adcs    %0, %0, %2
  122.     adcs    %0, %0, %3
  123.     adc    %0, %0, #0"
  124.     : "=&r"(sum)
  125.     : "r" (daddr), "r" (saddr), "r" ((ntohs(len)<<16)+proto*256), "0" (sum));
  126.     return sum;
  127. }    
  128. /*
  129.  * computes the checksum of the TCP/UDP pseudo-header
  130.  * returns a 16-bit checksum, already complemented
  131.  */
  132. static inline unsigned short int
  133. csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
  134.           unsigned short proto, unsigned int sum)
  135. {
  136.     return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
  137. }
  138.  
  139.  
  140. /*
  141.  * this routine is used for miscellaneous IP-like checksums, mainly
  142.  * in icmp.c
  143.  */
  144. static inline unsigned short
  145. ip_compute_csum(unsigned char * buff, int len)
  146. {
  147.     return csum_fold(csum_partial(buff, len, 0));
  148. }
  149.  
  150. #define _HAVE_ARCH_IPV6_CSUM
  151. extern unsigned long
  152. __csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
  153.         __u32 proto, unsigned int sum);
  154.  
  155. extern __inline__ unsigned short int
  156. csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
  157.         unsigned short proto, unsigned int sum)
  158. {
  159.     return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl((__u32)len),
  160.                        htonl(proto), sum));
  161. }
  162. #endif
  163.